package nl.windgazer.arachne.services.messages;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.services.ThreadLocale;

public class MessageInterceptEventListenerImpl implements
		MessageInterceptEventListener {

	private Logger logger = Logger.getLogger(MessageInterceptEventListenerImpl.class);

	private Map<String, InterceptedMessageVO> intercepted = new HashMap<String, InterceptedMessageVO>();

	private MarkupWriter writer = null;

	private ThreadLocale tl;

	private MessageInterceptorStorage mis;
	
	private static Pattern missingKeyRE = Pattern.compile("\\[\\[missing key:.*", Pattern.CASE_INSENSITIVE); 

	public MessageInterceptEventListenerImpl( MessageInterceptorStorage mis, ThreadLocale tl ) {
		this.mis = mis; 
		this.tl = tl; 
	}

	public void setMarkupWriter(MarkupWriter writer) {
		this.writer = writer;
	}
	
	private String get(String key, Locale locale) {
		Messages msgs = mis.getMessages(locale);
		if (msgs!=null) return msgs.get(key);
		else return null;
	}

	private String format(String key, Locale locale, Object... arg1) {
		Messages msgs = mis.getMessages(locale);
		if (msgs!=null) return msgs.format(key, arg1);
		else return null;
	}

	public String intercept(String key, String msg, Locale locale) {
		logger.debug(key + ":" + msg);
		if (locale == null) { //Don't know the exact circumstances, but sometimes the Locale specified, and this can cause problems with my in-mem storage...
			locale = tl.getLocale();
		}
		if (writer!=null && writer.getElement()!=null) {
			logger.debug("Trying to apply html-content on behalf of " + key + " in " + writer.getElement().getName());
			writer.getElement().attribute("translate", "messagekey:" + key);
		} else {
			logger.error("Message for '" + key + "' was not intercepted due to lack of MarkupWriter.");
		}
		String storedMsg = get(key, locale);
		if (null!=storedMsg && !missingKeyRE.matcher(storedMsg).matches()) {
			intercepted.put(key, new InterceptedMessageVO(key, storedMsg, msg, storedMsg)); //Non-formatted messages are the same as the property
			return storedMsg;
		}
		intercepted.put(key, new InterceptedMessageVO(key, msg, msg, msg)); //Non-formatted messages are the same as the property
		return msg;
	}

	public String intercept(String key, String msg, String property, Locale locale, Object... arg1) {
		logger.debug(key + ":" + msg);
		if (locale == null) {
			locale = tl.getLocale();
		}
		if (writer!=null && writer.getElement()!=null) {
			logger.debug("Trying to apply html-content on behalf of " + key + " in " + writer.getElement().getName());
			writer.getElement().attribute("translate", "messagekey:" + key);
		} else {
			logger.error("Message for '" + key + "' was not intercepted due to lack of MarkupWriter.");
		}
		String storedMsg = format(key, locale, arg1);
		if (null!=storedMsg && !missingKeyRE.matcher(storedMsg).matches()) {
			intercepted.put(key, new InterceptedMessageVO(key, storedMsg, msg, property));
			return storedMsg;
		}
		intercepted.put(key, new InterceptedMessageVO(key, msg, msg, property));
		return msg;
	}

	public Map<String, InterceptedMessageVO> getIntercepted() {
		return intercepted;
	}

	//Attempt at keeping this method thread-safe at least.
	public synchronized void addMsg(String key, String value, String pageName, Locale locale) {
		mis.addMsg( key, value, pageName, locale );
	}

	public synchronized List<TranslatedMessageVO> getAllTranslatedMessages() {
		return mis.getAllTranslatedMessages();
	}

}
